﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Elmah;
using Glimpse.Elmah.Configuration;

namespace Glimpse.Elmah.Infrastructure
{
	public class ErrorRepository : IRepository
	{
		private readonly IConfigurationReaderFactory _configurationReaderFactory;

		public ErrorRepository()
			: this(new ConfigurationReaderFactory())
		{
		}

		public ErrorRepository(IConfigurationReaderFactory configurationReaderFactory)
		{
			if (configurationReaderFactory == null)
				throw new ArgumentNullException("configurationReaderFactory");
			
			_configurationReaderFactory = configurationReaderFactory;
		}

        public ErrorPage GetErrorPage(HttpContextBase contextBase, int pageIndex, int pageSize)
		{
			// Validate parameters
            if (contextBase == null)
				return null;

			// Normalize the page index and size
			var actualPageIndex = Math.Max(0, pageIndex);
			var actualPageSize = Math.Min(Settings.MaximumPageSize, Math.Max(0, pageSize));
			if (actualPageSize == 0)
			{
				actualPageSize = Settings.DefaultPageSize;
			}

			// Get the errors from Elmah
			var errorList = new List<ErrorLogEntry>(pageSize);
            var totalCount = ErrorLog.GetDefault(contextBase.ApplicationInstance.Context).GetErrors(actualPageIndex, actualPageSize, errorList);
			if (totalCount == 0)
				return null;
            
			// Convert the Elmah errors to error info objects
            var path = VirtualPathUtility.ToAbsolute("~/", contextBase.Request.ApplicationPath);
			var errorPageUrl = GetErrorPageUrl();
			var errorInfoList = errorList
				.Select(errorEntry =>
				        new ErrorInfo
				        	{
				        		Id = errorEntry.Id,
				        		HostName = errorEntry.Error.HostName,
				        		StatusCode = errorEntry.Error.StatusCode,
				        		Type = errorEntry.Error.Type,
				        		Message = errorEntry.Error.Message,
				        		User = errorEntry.Error.User,
				        		Date = errorEntry.Error.Time,
				        		DetailsUrl = string.Format("<a href=\"{0}{1}/detail?id={2}&\" target=\"_blank\">View</a>", path, errorPageUrl, errorEntry.Id)
				        	})
				.ToList();

			// Return the error page
			var errorPage = new ErrorPage(actualPageIndex, actualPageSize, totalCount, errorInfoList);
			return errorPage;
		}

		private string GetErrorPageUrl()
		{
			var configurationReader = _configurationReaderFactory.Create();
			if (configurationReader == null)
				return null;

			var errorPageUrl = configurationReader.GetPathFor<ErrorLogPageFactory>();
			return errorPageUrl;
		}
	}
}